/**
 * @file example_003.cpp
 * @author 逆流 (1171267147@qq.com)
 * @brief 定时器组件
 * @version 1.0
 * @date 2025-06-18
 *
 * @copyright Copyright (c) 2025
 *
 */

#include <sys/times.h>

#include <boost/core/ignore_unused.hpp>
#include <iostream>

// #define BOOST_TIMER_ENABLE_DEPRECATED  // 旧版定时器组件

#ifdef BOOST_TIMER_ENABLE_DEPRECATED
#include <boost/timer.hpp>  // 仅引入头文件即可
#else
#include <boost/timer/timer.hpp>  // 新版定时器组件，需要链接 Boost Timer 库
#endif

#include <boost/chrono.hpp>
#include <boost/format.hpp>  // 引入 Boost Format 组件
#include <boost/thread.hpp>

using boost::format;
using std::cout;
using std::endl;

void test1() {
#ifdef BOOST_TIMER_ENABLE_DEPRECATED
    boost::timer t;

    cout << format("max time: %1 us%") % t.elapsed_max() << endl;

    cout << format("min time: %1% s") % t.elapsed_min() << endl;

    cout << format("elapsed time: %1% s") % t.elapsed() << endl;
#endif
}

void test2() {
    boost::timer::cpu_timer timer;

    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    // cout << format("max time: %1% s") % t.elapsed() << endl;
    cout << timer.format() << '\n';  // 1s
    timer.stop();                    // 停止计时器
    timer.resume();                  // 恢复计时器,继续计时
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    cout << timer.format() << '\n';  // 2s
    timer.stop();

    timer.start();  // 重新开始计时器
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    cout << timer.format() << '\n';  // 1s
}

class MyCpuTimer {
public:
    struct CpuTime {
        int64_t wall;    // 总时间
        int64_t user;    // 用户时间
        int64_t system;  // 系统时间
        void    clear() { wall = user = system = 0; }
    };
    MyCpuTimer() { start(); }
    ~MyCpuTimer() { stop(); }

    void start() {
        time_.clear();
        getCpuTime(time_);
    }
    void stop() {
        CpuTime current;
        getCpuTime(current);
        // 结束时间 - 开始时间 = 经历的时间
        time_.wall   = current.wall - time_.wall;      // 总时间
        time_.user   = current.user - time_.user;      // 用户时间
        time_.system = current.system - time_.system;  // 系统时间
        is_stopped_  = true;                           // 标记为已停止
    }

    CpuTime elapsed() {
        if (!is_stopped_) {
            CpuTime current;
            getCpuTime(current);
            // 结束时间 - 开始时间 = 经历的时间
            current.wall -= time_.wall;      // 总时间
            current.user -= time_.user;      // 用户时间
            current.system -= time_.system;  // 系统时间
            return current;                  // 返回当前计时结果
        }
        return time_;  // 如果已停止，直接返回之前的计时结果
    }

    static void getCpuTime(CpuTime &time) {
        // static int64_t    tf = sysconf(_SC_CLK_TCK);  // 每秒的系统时钟滴答数
        static int64_t nanosecond = 1e9 / sysconf(_SC_CLK_TCK);  // 换算为纳秒

        tms     tmp;
        clock_t total = times(&tmp);         // 获取当前进程的 CPU 时间(以时钟滴答为单位)
        time.wall     = total * nanosecond;  // 总时间
        time.user     = (tmp.tms_utime + tmp.tms_cutime) * nanosecond;  // 用户时间
        time.system   = (tmp.tms_stime + tmp.tms_cstime) * nanosecond;  // 系统时间
    }

protected:
    CpuTime time_;
    bool    is_stopped_ = false;  // 是否停止计时器
};

class MyAutoCpuTimer : public MyCpuTimer {
public:
    MyAutoCpuTimer() { start(); }
    ~MyAutoCpuTimer() {  // 通过析构函数自动停止并报告计时结果
        if (!is_stopped_) {
            report();  // 如果未停止，则报告计时结果
        }
    }

    void report() {
        stop();
        std::cout << format("wall: %1% us, user: %2% ms, system: %3% ms") % (time_.wall / 1e3) % (time_.user / 1e6) %
                         (time_.system / 1e6)
                  << '\n';  // 输出计时结果
    }
};

void test3() {
    MyCpuTimer timer;

    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    MyCpuTimer::CpuTime elapsed = timer.elapsed();
    cout << format("wall: %1% us, user: %2% ms, system: %3% ms") % (elapsed.wall / 1e3) % (elapsed.user / 1e6) %
                (elapsed.system / 1e6)
         << '\n';  // 1s
}

void test4() {
    MyAutoCpuTimer timer;

    boost::this_thread::sleep_for(boost::chrono::seconds(2));
    // 自动停止并报告计时结果
}

int main(int argc, char const *argv[]) {
    boost::ignore_unused(argc, argv);  // 忽略未使用的参数

    test1();

    test2();

    test3();

    test4();

    return 0;
}
